package com.hyperexcel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * @desc: 分批处理监听器（适用于大数据场景）
 * @author: Linbizhao
 * @date 2024年08月29日 12:16
 */
@Slf4j
@Getter
public class BatchProcessListener<T> extends AnalysisEventListener<T> {

    /**
     * 每批的处理行数（可以根据实际情况做出调整）
     */
    private static final Integer BATCH_COUNT = 1000;

    /**
     * 临时存储读取到的excel数据
     */
    private List<T> data;

    /**
     * 总行数、总批次
     */
    private int rows, batchNo;

    /**
     * 校验开关
     */
    private final boolean VALIDATE_SWITCH = true;

    /**
     * 每批数据的业务处理器
     */
    private final Consumer<List<T>> businessConsumer;

    /**
     * 用于校验excel模板正确性的字段
     */
    private final Field[] fields;

    /**
     * 泛型类
     */
    private final Class<T> clazz;

    public BatchProcessListener(List<T> data, Consumer<List<T>> businessConsumer, Field[] fields, Class<T> clazz) {
        this.data = data;
        this.businessConsumer = businessConsumer;
        this.fields = fields;
        this.clazz = clazz;
    }

    /**
     * 每一条数据解析都会调用
     */
    @Override
    public void invoke(T row, AnalysisContext context) {
        data.add(row);
        // 判断当前已解析的数据量是否达到本批上限，是则执对应的业务处理，防止数据几万条时内存溢出
        if (data.size() > BATCH_COUNT) {
            rows += data.size();
            batchNo++;

            businessConsumer.accept(data);
            data = new ArrayList<>(BATCH_COUNT);
        }
    }

    /**
     * 所以数据解析完成了后会调用此方法
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("所有数据解析完成...");

    }
}
